﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

namespace 桌面视频录制
{
    class VideoProcess
    {
        private string processFileName;//要处理的文件名
        private string saveFileName;//要保存的文件名
        private Bitmap processImage;//当前处理的一帧图片
        private long totalLength;

        public long TotalLength
        {
            get { return totalLength; }
        }
        private FileStream fs;
        private BinaryReader br;
        private BinaryWriter bw;
        private long frameIndex;
        private SortedList<long, ProcessFrame> frameSortedList = new SortedList<long, ProcessFrame>();
        public Bitmap ProcessImage
        {
            get { return processImage; }
            set { processImage = value; }
        }
        public VideoProcess(string processFileName, string saveFileName)
        {
            this.processFileName = processFileName;
            this.saveFileName = saveFileName;
            fs = File.OpenRead(processFileName);
            br = new BinaryReader(fs);
            this.totalLength = br.ReadInt64();
        }

        public void EndProcess()
        {
            long newTotalLength = 0;
            FileStream fss = File.OpenWrite(saveFileName);
            bw = new BinaryWriter(fss);
            bw.Write(newTotalLength);//写入新视频文件帧数 这时只是占位8字节 最后还要写入真实帧数
            bw.Flush();
            fs.Seek(8, SeekOrigin.Begin);
            for (int i = 0; i < totalLength; i++)
            {
                if (frameSortedList.Keys.Contains(i) == false)
                {
                    int length = br.ReadInt32();
                    bw.Write(length);
                    bw.Write(br.ReadBytes(length));
                    bw.Flush();
                    newTotalLength++;
                }
                else
                {
                    if (frameSortedList[i].IsDeleteFrame)
                    {
                        int length = br.ReadInt32();
                        fs.Seek(length, SeekOrigin.Current);
                    }
                    else
                    {
                        int length = br.ReadInt32();
                        byte[] bs = br.ReadBytes(length);
                        using (MemoryStream ms = new MemoryStream(bs))
                        {
                            using (Bitmap image = new Bitmap(ms))
                            {
                                Bitmap newImage = new Bitmap(frameSortedList[i].ImageSize.Width, frameSortedList[i].ImageSize.Height);
                                int dw = 0;
                                int dh = 0;
                                int width = newImage.Width;
                                int height = newImage.Height;
                                if (1.0 * newImage.Width / newImage.Height > 1.0 * image.Width / image.Height)
                                {
                                    width = image.Width * newImage.Height / image.Height;
                                    dw = (newImage.Width - width) / 2;
                                }
                                else
                                {
                                    height = image.Height * newImage.Width / image.Width;
                                    dh = (newImage.Height - height) / 2;
                                }
                                using (Graphics g = Graphics.FromImage(newImage))
                                {
                                    g.SmoothingMode = SmoothingMode.AntiAlias;
                                    g.Clear(Color.Black); 
                                    g.DrawImage(image, dw, dh, width, height);//将图像绘制在画布上  
                                    foreach (DrawObject drawObject in frameSortedList[i].DrawObjectList)
                                    {
                                        drawObject.Draw(g);
                                    }
                                }
                                using (MemoryStream mm = new MemoryStream())
                                {
                                    newImage.Save(mm, ImageFormat.Jpeg);
                                    byte[] bytes = mm.GetBuffer();
                                    bw.Write(bytes.Length);
                                    bw.Write(bytes);
                                    bw.Flush();
                                    newTotalLength++;
                                    newImage.Dispose();
                                    newImage = null;
                                }
                            }
                        }
                    }
                }
            }
            fss.Seek(0, SeekOrigin.Begin);
            bw.Write(newTotalLength);
            bw.Flush();
            fss.Close();
            bw.Close();
            fs.Close();
            br.Close();
        }
        private bool GetPlayPositon(BinaryReader br, FileStream fs, int offset)
        {
            try
            {
                fs.Seek(8, SeekOrigin.Begin);
                for (int i = 0; i < offset; i++)
                {
                    int length = br.ReadInt32();
                    fs.Seek(length, SeekOrigin.Current);
                }
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }
        public void SetProcessImage(int value)
        {
            this.frameIndex = value;
            if (GetPlayPositon(br, fs, value))
            {
                int length = br.ReadInt32();
                byte[] bs = br.ReadBytes(length);
                using (MemoryStream ms = new MemoryStream(bs))
                {
                    if (this.processImage != null)
                    {
                        this.processImage.Dispose();
                        this.processImage = null;
                    }
                    this.processImage = new Bitmap(ms);
                }
            }
        }

        public DrawObject GetDrawObject(string selectedNodeText, System.Windows.Forms.MouseEventArgs e)
        {
            DrawObject drawObject = null;
            switch (selectedNodeText)
            {
                case "直线":
                    drawObject = new DrawLine(e.Location, new Point(e.X + 1, e.Y));
                    break;
                case "虚线":
                    drawObject = new DrawDottedLine(e.Location, new Point(e.X + 1, e.Y));
                    break;
                case "直箭":
                    drawObject = new DrawLineWithCap(e.Location, new Point(e.X + 1, e.Y));
                    break;
                case "曲线":
                    drawObject = new DrawCurve(e.Location);
                    break;
                case "曲箭":
                    drawObject = new DrawCurveWithCap(e.Location);
                    break;
                case "矩形":
                    drawObject = new DrawRectangle(e.Location);
                    break;
                case "实矩":
                    drawObject = new DrawRectangleWithFill(e.Location);
                    break;
                case "实曲":
                    drawObject = new DrawClosedCurveWithFill(e.Location);
                    break;
                case "菱形":
                    drawObject = new DrawParallelogram(e.Location);
                    break;
                case "实菱":
                    drawObject = new DrawParallelogramWithFill(e.Location);
                    break;
                case "椭圆":
                    drawObject = new DrawEllipse(e.Location);
                    break;
                case "实圆":
                    drawObject = new DrawEllipseWithFill(e.Location);
                    break;
                case "弧线":
                    drawObject = new DrawArc(e.Location);
                    break;
                case "扇区":
                    drawObject = new DrawArcWithFill(e.Location);
                    break;
                case "橡皮":
                    drawObject = new DrawEraser(e.Location);
                    break;
                case "喷枪":
                    drawObject = new DrawAirBrush(e.Location);
                    break;
                case "圆柱":
                    drawObject = new DrawColumn(e.Location);
                    break;
                case "圆锥":
                    drawObject = new DrawCone(e.Location);
                    break;
                case "方体":
                    drawObject = new DrawCube(e.Location);
                    break;
                case "球体":
                    drawObject = new DrawSphere(e.Location);
                    break;
            }
            return drawObject;
        }

        public bool ProcessFrame(ProcessFrame processFrame)
        {
            if (frameSortedList.Keys.Contains(this.frameIndex))
            {
                if (MessageBox.Show("该帧已经处理过,确定要重新处理吗?", "警告!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes)
                    return false;
                this.frameSortedList[frameIndex] = processFrame;
                return true;
            }
            else
            {
                this.frameSortedList.Add(this.frameIndex, processFrame);
                return true;
            }
        }
    }
}
